/**
 * CanvasTerminal - 基于Canvas的终端模拟器
 * 负责终端的渲染、输入处理和尺寸调整
 */
class CanvasTerminal {
  /**
   * 创建一个新的Canvas终端
   * @param {Object} options - 终端配置选项
   */
  constructor(options = {}) {
    // 默认配置
    this.options = Object.assign({
      cols: 80,
      rows: 24,
      fontSize: 14,
      lineHeight: 1.2,
      fontFamily: '"Microsoft YaHei", "微软雅黑", "Noto Sans CJK SC", "Source Han Sans SC", "Source Han Sans CN", "WenQuanYi Micro Hei", Monaco, "Menlo", "Ubuntu Mono", monospace',
      foreground: '#ECECEC',
      background: '#000000',
      cursorColor: '#FFFFFF',
      cursorBlink: true,
      blinkInterval: 600
    }, options);

    // 初始化属性
    this.canvas = null;
    this.ctx = null;
    this.container = null;
    this.charWidth = 0;
    this.charHeight = 0;
    this.buffer = [];
    this.cursorX = 0;
    this.cursorY = 0;
    this.cursorVisible = true;
    this.cursorBlinkInterval = null;
    this.inputElement = null;
    this.dataListeners = [];
    this.ansiParser = null;
    this.scrollback = 1000; // 滚动历史行数
    this.scrollbackOffset = 0; // 当前滚动偏移量
    
    // 初始化缓冲区
    this._initBuffer();
  }

  /**
   * 初始化终端缓冲区
   */
  _initBuffer() {
    this.buffer = [];
    for (let y = 0; y < this.options.rows; y++) {
      const row = [];
      for (let x = 0; x < this.options.cols; x++) {
        row.push({
          char: ' ',
          fg: this.options.foreground,
          bg: this.options.background,
          bold: false,
          italic: false,
          underline: false,
          isFullWidth: false, // 添加标记是否为全角字符
          cellWidth: this.asciiCharWidth || this.options.fontSize // 添加单元格宽度属性，默认使用字体大小
        });
      }
      this.buffer.push(row);
    }
  }

  /**
   * 打开终端，初始化Canvas
   * @param {HTMLElement} container - 容器元素
   */
  open(container) {
    this.container = container;
    
    // 获取Canvas元素
    this.canvas = document.getElementById('terminal-canvas');
    this.ctx = this.canvas.getContext('2d');
    
    // 获取输入元素
    this.inputElement = document.getElementById('terminal-input');
    
    // 创建ANSI解析器
    this.ansiParser = new AnsiParser(this);
    
    // 设置字体
    this.ctx.font = `${this.options.fontSize}px ${this.options.fontFamily}`;
    
    // 计算字符尺寸
    this._calculateCharSize();
    
    // 调整Canvas大小
    this._resizeCanvas();
    
    // 初始化事件监听
    this._initEventListeners();
    
    // 启动光标闪烁
    if (this.options.cursorBlink) {
      this._startCursorBlink();
    }
    
    // 初始渲染
    this.render();
    
    // 聚焦输入框
    this.focus();
  }

  /**
   * 计算字符尺寸
   */
  _calculateCharSize() {
    // 创建一个临时的测量元素
    const tempSpan = document.createElement('span');
    tempSpan.style.font = this.ctx.font;
    tempSpan.style.position = 'absolute';
    tempSpan.style.visibility = 'hidden';
    tempSpan.style.whiteSpace = 'pre';
    
    // 测量ASCII字符宽度
    tempSpan.textContent = 'M'; // 使用M字符，通常是最宽的ASCII字符
    document.body.appendChild(tempSpan);
    const asciiRect = tempSpan.getBoundingClientRect();
    const asciiWidth = asciiRect.width;
    
    // 测量中文字符宽度
    tempSpan.textContent = '中';
    const cjkRect = tempSpan.getBoundingClientRect();
    const cjkWidth = cjkRect.width;
    
    // 设置ASCII字符单元格宽度
    this.asciiCharWidth = Math.ceil(asciiWidth);
    
    // 设置全角字符单元格宽度
    this.fullWidthCharWidth = Math.ceil(cjkWidth);
    
    // 使用ASCII字符宽度作为基础单元格宽度
    this.charWidth = this.asciiCharWidth;
    
    // 设置字符高度
    this.charHeight = this.options.fontSize * this.options.lineHeight;
    
    document.body.removeChild(tempSpan);
    
    console.log(`字符宽度计算 - ASCII宽度: ${asciiWidth}, 中文宽度: ${cjkWidth}, ASCII单元格宽度: ${this.asciiCharWidth}, 全角单元格宽度: ${this.fullWidthCharWidth}`);
  }

  /**
   * 检查字符是否是全角字符（中文、日文等）
   * @param {string} char - 要检查的字符
   * @returns {boolean} 是否是全角字符
   */
  isFullWidthChar(char) {
    // 使用Unicode范围检查是否是全角字符
    const code = char.charCodeAt(0);
    
    // 中文、日文、韩文等CJK字符
    if ((code >= 0x3000 && code <= 0x9FFF) ||   // CJK统一表意文字及标点
        (code >= 0xAC00 && code <= 0xD7AF) ||   // 韩文
        (code >= 0xFF00 && code <= 0xFFEF)) {   // 全角ASCII、全角标点
      return true;
    }
    
    return false;
  }

  /**
   * 解析颜色值，确保返回有效的CSS颜色
   * @param {string} color - 颜色值
   * @returns {string} 有效的CSS颜色
   */
  _parseColor(color) {
    // 如果颜色已经是有效的CSS颜色格式（如#RRGGBB），直接返回
    if (color && (color.startsWith('#') || color.startsWith('rgb') || color.startsWith('hsl'))) {
      return color;
    }
    
    // 如果是数字（ANSI颜色索引），转换为对应的颜色
    if (typeof color === 'number') {
      // 标准ANSI 16色
      if (color >= 0 && color <= 7) {
        return this._getANSIColor(color);
      }
      // 亮色ANSI 16色
      else if (color >= 8 && color <= 15) {
        return this._getANSIBrightColor(color - 8);
      }
      // 256色支持
      else if (color >= 16 && color <= 255) {
        return this._get256Color(color);
      }
    }
    
    // 如果是ANSI颜色名称，转换为对应的十六进制颜色
    const colorMap = {
      'black': '#000000',
      'red': '#CD0000',
      'green': '#00CD00',
      'yellow': '#CDCD00',
      'blue': '#0000EE',
      'magenta': '#CD00CD',
      'cyan': '#00CDCD',
      'white': '#E5E5E5',
      'brightBlack': '#7F7F7F',
      'brightRed': '#FF0000',
      'brightGreen': '#00FF00',
      'brightYellow': '#FFFF00',
      'brightBlue': '#5C5CFF',
      'brightMagenta': '#FF00FF',
      'brightCyan': '#00FFFF',
      'brightWhite': '#FFFFFF'
    };
    
    if (colorMap[color]) {
      return colorMap[color];
    }
    
    // 默认返回终端前景色
    return this.options.foreground;
  }
  
  /**
   * 获取ANSI标准颜色
   * @param {number} index - 颜色索引 (0-7)
   * @returns {string} 颜色代码
   */
  _getANSIColor(index) {
    const colors = [
      '#000000', // 黑
      '#CD0000', // 红
      '#00CD00', // 绿
      '#CDCD00', // 黄
      '#0000EE', // 蓝
      '#CD00CD', // 洋红
      '#00CDCD', // 青
      '#E5E5E5'  // 白
    ];
    return colors[index] || this.options.foreground;
  }

  /**
   * 获取ANSI亮色
   * @param {number} index - 颜色索引 (0-7)
   * @returns {string} 颜色代码
   */
  _getANSIBrightColor(index) {
    const brightColors = [
      '#7F7F7F', // 亮黑（灰）
      '#FF0000', // 亮红
      '#00FF00', // 亮绿
      '#FFFF00', // 亮黄
      '#5C5CFF', // 亮蓝
      '#FF00FF', // 亮洋红
      '#00FFFF', // 亮青
      '#FFFFFF'  // 亮白
    ];
    return brightColors[index] || this.options.foreground;
  }
  
  /**
   * 获取256色模式颜色
   * @param {number} index - 颜色索引 (16-255)
   * @returns {string} 颜色代码
   */
  _get256Color(index) {
    // 16-231: 6x6x6 颜色立方体
    if (index >= 16 && index <= 231) {
      index -= 16;
      const r = Math.floor(index / 36) * 51;
      const g = Math.floor((index % 36) / 6) * 51;
      const b = (index % 6) * 51;
      return `rgb(${r}, ${g}, ${b})`;
    }
    // 232-255: 灰度色阶
    else if (index >= 232 && index <= 255) {
      const gray = (index - 232) * 10 + 8;
      return `rgb(${gray}, ${gray}, ${gray})`;
    }
    
    return this.options.foreground;
  }

  /**
   * 计算每行的实际宽度，用于动态调整Canvas大小
   */
  _calculateRowWidth(rowIndex) {
    if (!this.buffer[rowIndex]) return 0;
    
    let totalWidth = 0;
    for (let x = 0; x < this.options.cols; x++) {
      const cell = this.buffer[rowIndex][x];
      totalWidth += cell.cellWidth || this.charWidth;
    }
    return totalWidth;
  }

  /**
   * 计算终端的最大宽度
   */
  _calculateMaxWidth() {
    let maxWidth = 0;
    for (let y = 0; y < this.options.rows; y++) {
      const rowWidth = this._calculateRowWidth(y);
      maxWidth = Math.max(maxWidth, rowWidth);
    }
    return maxWidth || this.options.cols * this.charWidth;
  }

  /**
   * 调整Canvas大小
   */
  _resizeCanvas() {
    // 使用动态计算的最大宽度
    const width = this._calculateMaxWidth();
    const height = this.options.rows * this.charHeight;
    
    this.canvas.width = width;
    this.canvas.height = height;
    
    // 重新设置字体，因为canvas尺寸改变会重置上下文
    this.ctx.font = `${this.options.fontSize}px ${this.options.fontFamily}`;
    
    // 更新终端尺寸显示
    document.getElementById('terminal-size').textContent = `列: ${this.options.cols}, 行: ${this.options.rows}`;
  }

  /**
   * 初始化事件监听
   */
  _initEventListeners() {
    // 窗口大小变化
    window.addEventListener('resize', () => {
      this.fit();
    });
    
    // 点击终端聚焦输入框
    this.container.addEventListener('click', () => {
      this.focus();
    });
    
    // 键盘输入
    this.inputElement.addEventListener('input', (e) => {
      const data = e.data || e.target.value;
      if (data) {
        this._emitData(data);
        e.target.value = '';
      }
    });
    
    // 特殊键处理
    this.inputElement.addEventListener('keydown', (e) => {
      let handled = false;
      
      // 处理特殊键
      switch (e.key) {
        case 'ArrowUp':
          this._emitData('\x1b[A');
          handled = true;
          break;
        case 'ArrowDown':
          this._emitData('\x1b[B');
          handled = true;
          break;
        case 'ArrowRight':
          this._emitData('\x1b[C');
          handled = true;
          break;
        case 'ArrowLeft':
          this._emitData('\x1b[D');
          handled = true;
          break;
        case 'Home':
          this._emitData('\x1b[H');
          handled = true;
          break;
        case 'End':
          this._emitData('\x1b[F');
          handled = true;
          break;
        case 'Delete':
          this._emitData('\x1b[3~');
          handled = true;
          break;
        case 'Backspace':
          this._emitData('\x7f');
          handled = true;
          break;
        case 'Tab':
          this._emitData('\t');
          handled = true;
          break;
        case 'Enter':
          this._emitData('\r');
          handled = true;
          break;
        case 'Escape':
          this._emitData('\x1b');
          handled = true;
          break;
      }
      
      // 处理组合键
      if (e.ctrlKey) {
        const code = e.key.charCodeAt(0);
        if (code >= 65 && code <= 90) { // A-Z
          this._emitData(String.fromCharCode(code - 64)); // 转换为控制字符
          handled = true;
        } else if (code >= 97 && code <= 122) { // a-z
          this._emitData(String.fromCharCode(code - 96)); // 转换为控制字符
          handled = true;
        }
      }
      
      if (handled) {
        e.preventDefault();
      }
    });
    
    // 粘贴处理
    this.inputElement.addEventListener('paste', (e) => {
      const text = e.clipboardData.getData('text');
      if (text) {
        this._emitData(text);
        e.preventDefault();
      }
    });
    
    // 滚轮事件处理（用于滚动历史）
    this.container.addEventListener('wheel', (e) => {
      if (e.deltaY !== 0) {
        const direction = e.deltaY > 0 ? 1 : -1; // 1 向下滚动，-1 向上滚动
        this._handleScroll(direction);
        e.preventDefault();
      }
    });
  }

  /**
   * 处理滚动
   * @param {number} direction - 滚动方向 (1: 向下, -1: 向上)
   */
  _handleScroll(direction) {
    // 暂时不实现滚动历史功能
    // 这里可以添加滚动历史的实现
  }

  /**
   * 发送数据事件
   * @param {string} data - 要发送的数据
   */
  _emitData(data) {
    this.dataListeners.forEach(callback => callback(data));
  }

  /**
   * 注册数据监听器
   * @param {function} callback - 数据回调函数
   */
  onData(callback) {
    this.dataListeners.push(callback);
  }

  /**
   * 写入数据到终端
   * @param {string} data - 要写入的数据
   */
  write(data) {
    // 确保数据是字符串
    if (typeof data !== 'string') {
      data = String(data);
    }
    
    // 记录写入前的光标位置，用于调试
    const oldX = this.cursorX;
    const oldY = this.cursorY;
    
    // 解析ANSI序列并更新终端状态
    this.ansiParser.parse(data);
    
    // 调试输出
    console.log(`写入数据: "${data.replace(/\x1b/g, '\\x1b')}", 光标移动: (${oldX},${oldY}) -> (${this.cursorX},${this.cursorY})`);
    
    // 渲染终端
    this.render();
  }

  /**
   * 渲染终端内容
   */
  render() {
    // 清空画布
    this.ctx.fillStyle = this.options.background;
    this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
    
    // 设置文本基线对齐方式，提高文本渲染精度
    this.ctx.textBaseline = 'top';
    
    // 渲染每个字符
    for (let y = 0; y < this.options.rows; y++) {
      let currentX = 0; // 当前行的实际X位置
      
      for (let x = 0; x < this.options.cols; x++) {
        const cell = this.buffer[y][x];
        
        // 使用已经设置的cellWidth，如果没有则使用默认值
        if (!cell.cellWidth) {
          const isFullWidth = this.isFullWidthChar(cell.char);
          cell.cellWidth = isFullWidth ? this.fullWidthCharWidth : this.asciiCharWidth;
          cell.isFullWidth = isFullWidth;
        }
        
        // 绘制背景 - 使用字符特定的单元格宽度
        const bgColor = this._parseColor(cell.bg);
        this.ctx.fillStyle = bgColor;
        this.ctx.fillRect(
          currentX,
          y * this.charHeight,
          cell.cellWidth,
          this.charHeight
        );
        
        // 如果是空格，跳过文本渲染但要更新位置
        if (cell.char === ' ') {
          currentX += cell.cellWidth;
          continue;
        }
        
        // 设置字体样式
        let fontStyle = '';
        if (cell.italic) fontStyle += 'italic ';
        if (cell.bold) fontStyle += 'bold ';
        this.ctx.font = `${fontStyle}${this.options.fontSize}px ${this.options.fontFamily}`;
        
        // 绘制文本 - 使用正确的前景颜色
        const fgColor = this._parseColor(cell.fg);
        this.ctx.fillStyle = fgColor;
        
        // 计算字符的X坐标，在当前单元格中居中显示
        let charX = currentX;
        const isFullWidth = cell.isFullWidth || this.isFullWidthChar(cell.char);
        if (isFullWidth) {
          // 全角字符：在其专用宽度中居中
          charX += (cell.cellWidth - this.fullWidthCharWidth) / 2;
        } else {
          // ASCII字符：在其专用宽度中居中
          charX += (cell.cellWidth - this.asciiCharWidth) / 2;
        }

        // 绘制文本
        this.ctx.fillText(
          cell.char,
          charX,
          y * this.charHeight + (this.charHeight - this.options.fontSize) / 2
        );
        
        // 绘制下划线
        if (cell.underline) {
          this.ctx.fillRect(
            currentX,
            y * this.charHeight + this.options.fontSize + 2,
            cell.cellWidth,
            1
          );
        }
        
        // 更新当前X位置
        currentX += cell.cellWidth;
      }
    }
    
    // 绘制光标
    if (this.cursorVisible && this.cursorX < this.options.cols && this.cursorY < this.options.rows) {
      // 计算光标位置的实际X坐标
      let cursorPixelX = 0;
      for (let x = 0; x < this.cursorX; x++) {
        const cell = this.buffer[this.cursorY][x];
        // 确保使用正确的宽度计算
        const isFullWidth = this.isFullWidthChar(cell.char);
        const cellWidth = isFullWidth ? this.fullWidthCharWidth : this.asciiCharWidth;
        cursorPixelX += cellWidth;
      }
      
      const cursorCell = this.buffer[this.cursorY][this.cursorX];
      const isFullWidthCursor = this.isFullWidthChar(cursorCell.char);
      const cursorWidth = isFullWidthCursor ? this.fullWidthCharWidth : this.asciiCharWidth;
      
      this.ctx.fillStyle = this.options.cursorColor;
      this.ctx.fillRect(
        cursorPixelX,
        this.cursorY * this.charHeight,
        cursorWidth,
        this.charHeight
      );
      
      // 绘制光标位置的字符（反色）
      if (cursorCell) {
        this.ctx.fillStyle = this._parseColor(cursorCell.bg);
        
        // 设置字体样式
        let fontStyle = '';
        if (cursorCell.italic) fontStyle += 'italic ';
        if (cursorCell.bold) fontStyle += 'bold ';
        this.ctx.font = `${fontStyle}${this.options.fontSize}px ${this.options.fontFamily}`;
        
        // 计算字符在光标中的位置
        let charX = cursorPixelX;
        if (isFullWidthCursor) {
          // 全角字符居中显示
          charX += (cursorWidth - this.fullWidthCharWidth) / 2;
        } else {
          // ASCII字符居中显示
          charX += (cursorWidth - this.asciiCharWidth) / 2;
        }
        
        this.ctx.fillText(
          cursorCell.char,
          charX,
          this.cursorY * this.charHeight + (this.charHeight - this.options.fontSize) / 2
        );
      }
    }
  }

  /**
   * 启动光标闪烁
   */
  _startCursorBlink() {
    if (this.cursorBlinkInterval) {
      clearInterval(this.cursorBlinkInterval);
    }
    
    this.cursorBlinkInterval = setInterval(() => {
      this.cursorVisible = !this.cursorVisible;
      this.render();
    }, this.options.blinkInterval);
  }

  /**
   * 停止光标闪烁
   */
  _stopCursorBlink() {
    if (this.cursorBlinkInterval) {
      clearInterval(this.cursorBlinkInterval);
      this.cursorBlinkInterval = null;
    }
    this.cursorVisible = true;
  }

  /**
   * 设置光标位置
   * @param {number} x - 列位置
   * @param {number} y - 行位置
   */
  setCursor(x, y) {
    this.cursorX = Math.max(0, Math.min(x, this.options.cols - 1));
    this.cursorY = Math.max(0, Math.min(y, this.options.rows - 1));
    this.render();
  }

  /**
   * 清空屏幕
   */
  clear() {
    this._initBuffer();
    this.cursorX = 0;
    this.cursorY = 0;
    this.render();
  }

  /**
   * 聚焦终端
   */
  focus() {
    if (this.inputElement) {
      this.inputElement.focus();
    }
  }

  /**
   * 调整终端大小以适应容器
   */
  fit() {
    const containerWidth = this.container.clientWidth - 20; // 减去padding
    const containerHeight = this.container.clientHeight - 20;
    
    // 计算可容纳的列数和行数
    const cols = Math.floor(containerWidth / this.charWidth);
    const rows = Math.floor(containerHeight / this.charHeight);
    
    // 更新终端尺寸
    this.resize(cols, rows);
  }

  /**
   * 调整终端大小
   * @param {number} cols - 列数
   * @param {number} rows - 行数
   */
  resize(cols, rows) {
    // 保存旧的缓冲区
    const oldBuffer = this.buffer;
    
    // 更新尺寸
    this.options.cols = cols;
    this.options.rows = rows;
    
    // 初始化新缓冲区
    this._initBuffer();
    
    // 复制旧缓冲区内容到新缓冲区
    for (let y = 0; y < Math.min(rows, oldBuffer.length); y++) {
      for (let x = 0; x < Math.min(cols, oldBuffer[y].length); x++) {
        this.buffer[y][x] = oldBuffer[y][x];
        // 确保复制的单元格有正确的cellWidth
        const cell = this.buffer[y][x];
        if (cell) {
          const isFullWidth = this.isFullWidthChar(cell.char);
          cell.cellWidth = isFullWidth ? this.fullWidthCharWidth : this.asciiCharWidth;
          cell.isFullWidth = isFullWidth;
        }
      }
    }
    
    // 调整Canvas大小
    this._resizeCanvas();
    
    // 确保光标在有效范围内
    this.cursorX = Math.min(this.cursorX, cols - 1);
    this.cursorY = Math.min(this.cursorY, rows - 1);
    
    // 重新渲染
    this.render();
  }
}